# -*- coding:utf-8 -*-
# /views/admin.py    管理后台视图

from flask import *
from flask_sqlalchemy import *
import json

from exts import *
from tools import *
from testdata_syncer_client import *


admin = Blueprint("admin", __name__, template_folder = "templates")


@admin.route("/init_db")
def init_db():
    db.create_all()
    is_set = Setting.query.filter().first()
    if is_set:
        return "数据库已经初始化过"
    setting_oj_name = Setting(key = "oj_name", value = "JudgeChickenOnlineJudge")
    db.session.add(setting_oj_name)
    setting_oj_name_abb = Setting(key = "oj_name_abb", value = "JCOJ")
    db.session.add(setting_oj_name_abb)
    setting_password = Setting(key = "password", value = "ba3253876aed6bc22d4a6ff53d8406c6ad864195ed144ab5c87621b6c23\
3b548baeae6956df346ec8c17f5ea10f35ee3cbc514797ed7ddd3145464e2a0bab413")
    db.session.add(setting_password)
    setting_notice_markdown = Setting(key = "notice_markdown", value = "# 欢迎来到JudgeChickenOnlineJudge")
    db.session.add(setting_notice_markdown)
    setting_notice_html = Setting(key = "notice_html", value = markdown_to_html("# 欢迎来到JudgeChickenOnlineJudge"))
    db.session.add(setting_notice_html)
    setting_board = Setting(key = "board", value = "[]")
    db.session.add(setting_board)
    db.session.commit()
    return "成功初始化数据库"


@admin.route("/login", methods = ["GET", "POST"])
def login():
    if request.method == "GET":
        if not_login():
            template_data = {
                "global": {
                    "name": Setting.query.filter(Setting.key == "oj_name").first().value,
                    "abb_name": Setting.query.filter(Setting.key == "oj_name_abb").first().value
                },
                "general": {
                }
            }
            return render_template("admin/login.html", **template_data)
        else:
            return redirect(url_for("admin.index"))
    else:
        password_input = request.form.get("password")
        password_correct_hash = Setting.query.filter(Setting.key == "password").first().value
        if sha512(password_input) == password_correct_hash:
            session["admin_login"] = password_correct_hash
            return redirect(url_for("admin.index"))
        else:
            template_data = {
                "global": {
                    "name": Setting.query.filter(Setting.key == "oj_name").first().value,
                    "abb_name": Setting.query.filter(Setting.key == "oj_name_abb").first().value
                },
                "general": {
                }
            }
            return render_template("admin/login.html", **template_data, wrong_password = True)


@admin.route("/")
def index():
    if not_login():
        return redirect(url_for("admin.login"))
    template_data = {
        "global": {
            "name": Setting.query.filter(Setting.key == "oj_name").first().value,
            "abb_name": Setting.query.filter(Setting.key == "oj_name_abb").first().value
        },
        "general": {
            "title": "概览",
            "subtitle": ""
        },
        "private": {
        }
    }
    return render_template("admin/index.html", **template_data)


@admin.route("/problem/search", methods = ["GET", "POST"])
def problem_search():
    if not_login():
        return redirect(url_for("admin.login"))
    if request.method == "GET":
        template_data = {
            "global": {
                "name": Setting.query.filter(Setting.key == "oj_name").first().value,
                "abb_name": Setting.query.filter(Setting.key == "oj_name_abb").first().value
            },
            "general": {
                "title": "题目编辑",
                "subtitle": ""
            }
        }
        return render_template("admin/problem_search.html", **template_data)
    else:
        input_problem_id = request.form.get("problem_id")
        problem = Problem.query.filter(Problem.id == int(input_problem_id)).first()
        if problem:
            return redirect(url_for("admin.problem_edit", problem_id = int(input_problem_id)))
        else:
            template_data = {
                "global": {
                    "name": Setting.query.filter(Setting.key == "oj_name").first().value,
                    "abb_name": Setting.query.filter(Setting.key == "oj_name_abb").first().value
                },
                "general": {
                    "title": "题目编辑",
                    "subtitle": ""
                }
            }
            return render_template("admin/problem_search.html", **template_data, wrong_problem_id = True)


@admin.route("/problem/edit/<problem_id>", methods = ["GET", "POST"])
def problem_edit(problem_id):
    if not_login():
        return redirect(url_for("admin.login"))
    if request.method == "GET":
        problem = Problem.query.filter(Problem.id == int(problem_id)).first()
        if not problem:
            return redirect(url_for("admin.problem_search"))
        template_data = {
            "global": {
                "name": Setting.query.filter(Setting.key == "oj_name").first().value,
                "abb_name": Setting.query.filter(Setting.key == "oj_name_abb").first().value
            },
            "general": {
                "title": "题目编辑 #" + str(problem_id),
                "subtitle": ""
            },
            "problem_data": {
                "id": problem.id,
                "name": problem.name,
                "description": problem.description_markdown,
                "answer": problem.answer_markdown
            }
        }
        return render_template("admin/problem_edit.html", **template_data)
    else:
        input_name = request.form.get("name")
        input_description = request.form.get("description")
        input_answer = request.form.get("answer")
        problem = Problem.query.filter(Problem.id == int(problem_id)).first()
        problem.name = input_name
        problem.description_markdown = input_description
        problem.description_html = markdown_to_html(input_description)
        problem.answer_markdown = input_answer
        problem.answer_html = markdown_to_html(input_answer)
        db.session.commit()
        return redirect(url_for("admin.problem_edit", problem_id = problem_id))


@admin.route("/problem/delete/<problem_id>")
def problem_delete(problem_id):
    if not_login():
        return redirect(url_for("admin.login"))
    problem = Problem.query.filter(Problem.id == int(problem_id)).first()
    if problem:
        board = Board.query.filter(Board.name == "题目#" + problem_id).first()
        discuss_id_list = json.loads(board.discuss)
        for discuss_id in discuss_id_list:
            discuss = Discuss.query.filter(Discuss.id == discuss_id).first()
            db.session.delete(discuss)
        db.session.delete(board)
        db.session.delete(problem)
        db.session.commit()
        test_data_syncer_delete_data(problem_id)
    return redirect(url_for("admin.problem_search"))


@admin.route("/problem/new", methods = ["GET", "POST"])
def problem_new():
    if not_login():
        return redirect(url_for("admin.login"))
    if request.method == "GET":
        template_data = {
            "global": {
                "name": Setting.query.filter(Setting.key == "oj_name").first().value,
                "abb_name": Setting.query.filter(Setting.key == "oj_name_abb").first().value
            },
            "general": {
                "title": "新建题目",
                "subtitle": ""
            }
        }
        return render_template("admin/problem_new.html", **template_data)
    else:
        input_name = request.form.get("name")
        input_description = request.form.get("description")
        problem = Problem(
            id = Problem.query.count() + 1,
            name = input_name,
            description_markdown = input_description,
            description_html = markdown_to_html(input_description)
        )
        board = Board(
            name = "题目#" + str(Problem.query.count() + 1),
            discuss = "[]"
        )
        db.session.add(problem)
        db.session.add(board)
        db.session.commit()
        return redirect(url_for("admin.problem_search"))


@admin.route("/problem/upload", methods = ["GET", "POST"])
def problem_upload():
    if not_login():
        return redirect(url_for("admin.login"))
    if request.method == "GET":
        template_data = {
            "global": {
                "name": Setting.query.filter(Setting.key == "oj_name").first().value,
                "abb_name": Setting.query.filter(Setting.key == "oj_name_abb").first().value
            },
            "general": {
                "title": "上传题目测试数据",
                "subtitle": ""
            }
        }
        return render_template("admin/problem_upload.html", **template_data)
    else:
        if "file" not in request.files:
            template_data = {
                "global": {
                    "name": Setting.query.filter(Setting.key == "oj_name").first().value,
                    "abb_name": Setting.query.filter(Setting.key == "oj_name_abb").first().value
                },
                "general": {
                    "title": "上传题目测试数据",
                    "subtitle": ""
                }
            }
            return render_template("admin/problem_upload.html", **template_data, upload_failed = True)
        file_data = request.files["file"]
        if file_data.filename == "":
            template_data = {
                "global": {
                    "name": Setting.query.filter(Setting.key == "oj_name").first().value,
                    "abb_name": Setting.query.filter(Setting.key == "oj_name_abb").first().value
                },
                "general": {
                    "title": "上传题目测试数据",
                    "subtitle": ""
                }
            }
            return render_template("admin/problem_upload.html", **template_data, upload_failed = True)
        filename = "%s.zip" % (datetime.datetime.now())
        file_data.save(config.UPLOAD_FOLDER + "/" + filename)
        test_data_syncer_upload_data(config.UPLOAD_FOLDER + "/" + filename)
        os.remove(config.UPLOAD_FOLDER + "/" + filename)
        return redirect(url_for("admin.problem_search"))


@admin.route("/setting", methods = ["GET", "POST"])
def setting():
    if not_login():
        return redirect(url_for("admin.login"))
    if request.method == "GET":
        template_data = {
            "global": {
                "name": Setting.query.filter(Setting.key == "oj_name").first().value,
                "abb_name": Setting.query.filter(Setting.key == "oj_name_abb").first().value
            },
            "general": {
                "title": "设置",
                "subtitle": ""
            },
            "private": {
                "oj_name": Setting.query.filter(Setting.key == "oj_name").first().value,
                "oj_name_abb": Setting.query.filter(Setting.key == "oj_name_abb").first().value
            }
        }
        return render_template("admin/setting.html", **template_data)
    else:
        input_oj_name = request.form.get("oj_name")
        input_oj_name_abb = request.form.get("oj_name_abb")
        oj_name = Setting.query.filter(Setting.key == "oj_name").first()
        oj_name_abb = Setting.query.filter(Setting.key == "oj_name_abb").first()
        oj_name.value = input_oj_name
        oj_name_abb.value = input_oj_name_abb
        db.session.commit()

        message_password = None
        input_password_old = request.form.get("password_old")
        input_password_new = request.form.get("password_new")
        input_password_rep = request.form.get("password_rep")
        if input_password_old != "":
            setting_password = Setting.query.filter(Setting.key == "password").first()
            if sha512(input_password_old) != setting_password.value:
                message_password = "原密码错误"
            elif input_password_new != input_password_rep:
                message_password = "两次密码输入不一致"
            else:
                setting_password.value = sha512(input_password_new)
                db.session.commit()
        template_data = {
            "global": {
                "name": Setting.query.filter(Setting.key == "oj_name").first().value,
                "abb_name": Setting.query.filter(Setting.key == "oj_name_abb").first().value
            },
            "general": {
                "title": "设置",
                "subtitle": ""
            },
            "private": {
                "oj_name": Setting.query.filter(Setting.key == "oj_name").first().value,
                "oj_name_abb": Setting.query.filter(Setting.key == "oj_name_abb").first().value,
                "password_message": message_password
            }
        }
        return render_template("admin/setting.html", **template_data)


@admin.route("/notice/edit", methods = ["GET", "POST"])
def notice_edit():
    if not_login():
        return redirect(url_for("admin.login"))
    if request.method == "GET":
        template_data = {
            "global": {
                "name": Setting.query.filter(Setting.key == "oj_name").first().value,
                "abb_name": Setting.query.filter(Setting.key == "oj_name_abb").first().value
            },
            "general": {
                "title": "公告板编辑",
                "subtitle": ""
            },
            "private": {
                "content": Setting.query.filter(Setting.key == "notice_markdown").first().value
            }
        }
        return render_template("admin/notice_edit.html", **template_data)
    else:
        input_content = request.form.get("content")
        setting_notice_markdown = Setting.query.filter(Setting.key == "notice_markdown").first()
        setting_notice_html = Setting.query.filter(Setting.key == "notice_html").first()
        setting_notice_markdown.value = input_content
        setting_notice_html.value = markdown_to_html(input_content)
        db.session.commit()
        return redirect(url_for("admin.notice_edit"))


@admin.route("/board/new", methods = ["GET", "POST"])
def board_new():
    if not_login():
        return redirect(url_for("admin.login"))
    if request.method == "GET":
        template_data = {
            "global": {
                "name": Setting.query.filter(Setting.key == "oj_name").first().value,
                "abb_name": Setting.query.filter(Setting.key == "oj_name_abb").first().value
            },
            "general": {
                "title": "新建讨论版",
                "subtitle": ""
            }
        }
        return render_template("admin/board_new.html", **template_data)
    else:
        input_board_name = request.form.get("board_name")
        board = Board(name = input_board_name, discuss = "[]")
        db.session.add(board)
        setting_board = Setting.query.filter(Setting.key == "board").first()
        setting_board_obj = json.loads(setting_board.value)
        setting_board_obj.append(input_board_name)
        setting_board.value = json.dumps(setting_board_obj)
        db.session.commit()
        return redirect(url_for("admin.board_new"))


@admin.route("/board/edit", methods = ["GET", "POST"])
def board_edit():
    if not_login():
        return redirect(url_for("admin.login"))
    if request.method == "GET":
        template_data = {
            "global": {
                "name": Setting.query.filter(Setting.key == "oj_name").first().value,
                "abb_name": Setting.query.filter(Setting.key == "oj_name_abb").first().value
            },
            "general": {
                "title": "编辑讨论版",
                "subtitle": ""
            }
        }
        return render_template("admin/board_edit.html", **template_data)
    else:
        input_board_name_old = request.form.get("board_name_old")
        input_board_name_new = request.form.get("board_name_new")
        board = Board.query.filter(Board.name == input_board_name_old).first()
        if not board:
            template_data = {
                "global": {
                    "name": Setting.query.filter(Setting.key == "oj_name").first().value,
                    "abb_name": Setting.query.filter(Setting.key == "oj_name_abb").first().value
                },
                "general": {
                    "title": "编辑讨论版",
                    "subtitle": ""
                }
            }
            return render_template("admin/board_edit.html", **template_data, message = "讨论版不存在")
        if input_board_name_new != "":
            board.name = input_board_name_new
            setting_board = Setting.query.filter(Setting.key == "board").first()
            setting_board_obj = json.loads(setting_board.value)
            setting_board_obj.remove(input_board_name_old)
            setting_board_obj.append(input_board_name_new)
            setting_board.value = json.dumps(setting_board_obj)
            db.session.commit()
        else:
            discuss_id_list = json.loads(board.discuss)
            for discuss_id in discuss_id_list:
                discuss = Discuss.query.filter(Discuss.id == discuss_id).first()
                db.session.delete(discuss)
            db.session.delete(board)
            setting_board = Setting.query.filter(Setting.key == "board").first()
            setting_board_obj = json.loads(setting_board.value)
            setting_board_obj.remove(input_board_name_old)
            setting_board.value = json.dumps(setting_board_obj)
            db.session.commit()
        return redirect(url_for("admin.board_edit"))


def not_login():
    session_string = Setting.query.filter(Setting.key == "password").first().value
    if not (session.get("admin_login", default = False) == session_string):
        return True
    else:
        return False
